package com.yt.project.service.impl;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yt.project.model.entity.UpInfo;
import com.yt.project.model.entity.User;
import com.yt.project.model.vo.UpInfoVO;
import com.yt.project.service.UpInfoService;
import com.yt.project.mapper.UpInfoMapper;
import com.yt.project.service.UserService;
import com.yt.project.utils.AlgorithmUtils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
* @author lenovo
* @description 针对表【up_info】的数据库操作Service实现
* @createDate 2023-04-23 13:46:15
*/
@Service
public class UpInfoServiceImpl extends ServiceImpl<UpInfoMapper, UpInfo>
    implements UpInfoService{

    @Resource
    private UserService userService;

    private Gson gson = new Gson();


    @Override
    public List<UpInfoVO> getRecommendUps(long pageNum, long pageSize) {
        Page<UpInfo> upInfoPage = page(new Page<>(pageNum, pageSize));
        Page<UpInfoVO> upInfoVOPage = new Page<>();
        List<UpInfoVO> upInfoVOS = upInfoPage.getRecords().stream().map(upInfo -> {
            UpInfoVO upInfoVO = new UpInfoVO();
            upInfoVO.setId(upInfo.getId());
            upInfoVO.setUpName(upInfo.getUpName());
            upInfoVO.setGender(upInfo.getGender());
            upInfoVO.setRegion(upInfo.getRegion());
            upInfoVO.setIntroduction(upInfo.getIntroduction());
            upInfoVO.setAvgPlayCount(upInfo.getAvgPlayCount());
            upInfoVO.setAvgLikeCount(upInfo.getAvgLikeCount());
            upInfoVO.setAvgFavoriteCount(upInfo.getAvgFavoriteCount());
            upInfoVO.setAvgShareCount(upInfo.getAvgShareCount());
            upInfoVO.setAvgCommentCount(upInfo.getAvgCommentCount());
            upInfoVO.setAvgDanmuCount(upInfo.getAvgDanmuCount());
            upInfoVO.setEmbeddedVideo(upInfo.getEmbeddedVideo());
            upInfoVO.setCustomizedVideo(upInfo.getCustomizedVideo());
            upInfoVO.setPostedDynamic(upInfo.getPostedDynamic());
            upInfoVO.setRepostedDynamic(upInfo.getRepostedDynamic());
            upInfoVO.setLink(upInfo.getLink());
            upInfoVO.setAvatar(upInfo.getAvatar());
            List<String> tags = gson.fromJson(upInfo.getTags(), new TypeToken<List<String>>(){}.getType());
            upInfoVO.setTags(tags);
            return upInfoVO;
        }).collect(Collectors.toList());
        return upInfoVOS;
    }

    @Override
    public List<UpInfoVO> matchUps(User loginUser, long num) {
        QueryWrapper<UpInfo> upInfoQueryWrapper = new QueryWrapper<>();
        upInfoQueryWrapper.and(qw -> qw.isNotNull("tags").or().ne("tags", "[]"));
        upInfoQueryWrapper.select("id", "tags");
        List<UpInfo> list = this.list(upInfoQueryWrapper);
        List<UpInfoVO> result = new ArrayList<>();
        SortedMap<Integer, Integer> indexDistanceMap = new TreeMap<>((a,b) -> a - b);
        String tags = loginUser.getTags();
        List<String> userTagsList = gson.fromJson(tags, new TypeToken<List<String>>(){}.getType());
        if (StringUtils.isBlank(tags) || "[]".equals(tags)) {
            List<UpInfoVO> upInfoVOPage = this.getRecommendUps(0, num);
            return upInfoVOPage;
        } else {
            List<Pair<UpInfo, Integer>> list1 = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                String upTags = list.get(i).getTags();
                if (StringUtils.isBlank(upTags) || "[]".equals(upTags)) {
                    continue;
                }
                List<String> upTagsList = gson.fromJson(upTags, new TypeToken<List<String>>(){}.getType());
                int distance = AlgorithmUtils.minDistance(upTagsList, userTagsList);
                indexDistanceMap.put(i, distance);
                list1.add(new Pair<>(list.get(i), distance));
            }
            List<Pair<UpInfo, Integer>> topUserPairList = list1.stream().sorted((a, b) -> a.getValue() - b.getValue()).limit(num).collect(Collectors.toList());
            List<Integer> idList = topUserPairList.stream().map(pair -> pair.getKey().getId()).collect(Collectors.toList());
            QueryWrapper<UpInfo> queryWrapper = new QueryWrapper<>();
            String joinStr = StrUtil.join(",", idList);
            queryWrapper.in("id", idList).last(" order by field (id," + joinStr + ")");
            result = this.list(queryWrapper).stream().map(upInfo -> {
                UpInfoVO upInfoVO = new UpInfoVO();
                upInfoVO.setId(upInfo.getId());
                upInfoVO.setUpName(upInfo.getUpName());
                upInfoVO.setGender(upInfo.getGender());
                upInfoVO.setRegion(upInfo.getRegion());
                upInfoVO.setIntroduction(upInfo.getIntroduction());
                upInfoVO.setAvgPlayCount(upInfo.getAvgPlayCount());
                upInfoVO.setAvgLikeCount(upInfo.getAvgLikeCount());
                upInfoVO.setAvgFavoriteCount(upInfo.getAvgFavoriteCount());
                upInfoVO.setAvgShareCount(upInfo.getAvgShareCount());
                upInfoVO.setAvgCommentCount(upInfo.getAvgCommentCount());
                upInfoVO.setAvgDanmuCount(upInfo.getAvgDanmuCount());
                upInfoVO.setEmbeddedVideo(upInfo.getEmbeddedVideo());
                upInfoVO.setCustomizedVideo(upInfo.getCustomizedVideo());
                upInfoVO.setPostedDynamic(upInfo.getPostedDynamic());
                upInfoVO.setRepostedDynamic(upInfo.getRepostedDynamic());
                upInfoVO.setAvatar(upInfo.getAvatar());
                upInfoVO.setLink(upInfo.getLink());
                List<String> tmpTags = gson.fromJson(upInfo.getTags(), new TypeToken<List<String>>(){}.getType());
                upInfoVO.setTags(tmpTags);
                return upInfoVO;
            }).collect(Collectors.toList());
        }
        return result;
    }
}




